package com.roads.site.service.impl;

import com.roads.common.config.MasterConfig;
import com.roads.common.constant.Constants;
import com.roads.common.constant.ResultConstants;
import com.roads.common.constant.UserConstants;
import com.roads.common.core.domain.AjaxResult;
import com.roads.common.core.domain.ExcelResult;
import com.roads.common.utils.DateUtils;
import com.roads.common.utils.SecurityUtils;
import com.roads.common.utils.StringUtils;
import com.roads.common.utils.file.FileUtils;
import com.roads.common.utils.uuid.IdUtils;
import com.roads.site.domain.SiteLabourStaff;
import com.roads.site.domain.SiteLabourStaffSalaryAnnex;
import com.roads.site.domain.SiteLabourStaffSalaryDetail;
import com.roads.site.domain.SiteLabourStaffSalaryMaster;
import com.roads.site.mapper.SiteLabourStaffMapper;
import com.roads.site.mapper.SiteLabourStaffSalaryAnnexMapper;
import com.roads.site.mapper.SiteLabourStaffSalaryDetailMapper;
import com.roads.site.mapper.SiteLabourStaffSalaryMasterMapper;
import com.roads.site.service.ISiteLabourStaffSalaryService;
import com.roads.site.utils.CardUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 劳务工-工资Service业务层处理
 *
 * @author nhp
 * @date 2022-11-15
 */
@Service
public class SiteLabourStaffSalaryServiceImpl implements ISiteLabourStaffSalaryService {

    @Autowired
    private SiteLabourStaffSalaryMasterMapper masterMapper;

    @Autowired
    private SiteLabourStaffSalaryDetailMapper detailMapper;

    @Autowired
    private SiteLabourStaffSalaryAnnexMapper annexMapper;

    @Autowired
    private SiteLabourStaffMapper staffMapper;

    /**
     * 查询劳务工工资列表
     *
     * @param model 劳务工资
     * @return 劳务工资集合
     */
    @Override
    public List<SiteLabourStaffSalaryMaster> selectMasterModelList(SiteLabourStaffSalaryMaster model) {
        return masterMapper.selectModelList(model);
    }

    /**
     * 查询劳务工工资明细列表
     *
     * @param model 劳务工资明细
     * @return 劳务工资明细集合
     */
    @Override
    public List<SiteLabourStaffSalaryDetail> selectDetailModelList(SiteLabourStaffSalaryDetail model) {
        return detailMapper.selectModelList(model);
    }

    /**
     * 查询劳务工工资附件列表
     *
     * @param model 劳务工资附件
     * @return 劳务工资附件集合
     */
    @Override
    public List<SiteLabourStaffSalaryAnnex> selectAnnexList(SiteLabourStaffSalaryAnnex model) {
        return annexMapper.selectModelList(model);
    }

    /**
     * 检查工资发放日期是否唯一（同一个项目标段下）
     *
     * @param model 劳务工工资
     * @return 结果
     */
    @Override
    public String checkSalaryDateUnique(SiteLabourStaffSalaryMaster model) {
        Integer masterId = StringUtils.isNull(model.getMasterId()) ? -1 : model.getMasterId();
        SiteLabourStaffSalaryMaster info = masterMapper.checkSalaryDateUnique(model.getInstitutionCode(), model.getSalaryDate());
        if (StringUtils.isNotNull(info) && !info.getMasterId().equals(masterId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 新增劳务工工资
     *
     * @param master 劳务工工资主表
     * @return 结果
     */
    @Override
    public int addMaster(SiteLabourStaffSalaryMaster master) {
        master.setSalaryDateYear(master.getSalaryDate().substring(0, 4));
        master.setSalaryDateMonth(master.getSalaryDate().substring(5));
        String uuid = IdUtils.simpleUuid();
        master.setAnnexUuid(uuid);
        master.setHasAnnex(Constants.NO);
        master.setCreateBy(SecurityUtils.getUsername());
        master.setCreateTime(DateUtils.getNowDate());
        return masterMapper.insert(master);
    }

    /**
     * 新增劳务工工资明细
     *
     * @param detail 劳务工工资明细
     * @return 结果
     */
    @Override
    public int addDetail(SiteLabourStaffSalaryDetail detail) {
        SiteLabourStaff staff = staffMapper.getModelById(detail.getStaffId());
        detail.setIdNo(staff.getIdNo());
        detail.setName(staff.getName());
        detail.setBattalionId(staff.getBattalionId());
        detail.setTeamId(staff.getTeamId());
        detail.setPostId(staff.getPostId());
        detail.setCreateBy(SecurityUtils.getUsername());
        detail.setCreateTime(DateUtils.getNowDate());
        return detailMapper.insert(detail);
    }

    /**
     * 新增劳务工工资附件
     *
     * @param model 附件
     * @param uuid uuid
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertAnnex(SiteLabourStaffSalaryAnnex model, String uuid) {
        int result = 0;
        // 查询一下文件数量。数量等于0，则需要更新状态
        int count = annexMapper.getFileCount(uuid);
        if (count == 0) {
            result = 1;
            masterMapper.updateAnnexStatus(uuid, Constants.YES);
        }
        annexMapper.insert(model);
        return result;
    }

    /**
     * 获取劳务工工资详情
     *
     * @param id 主键
     * @return 劳务工工资
     */
    @Override
    public SiteLabourStaffSalaryMaster getMaster(Integer id) {
        return masterMapper.getModelById(id);
    }

    /**
     * 获取劳务工工资明细详情
     *
     * @param id 主键
     * @return 劳务工工资明细
     */
    @Override
    public SiteLabourStaffSalaryDetail getDetail(Integer id) {
        return detailMapper.getModelById(id);
    }

    /**
     * 根据主键ID获取附件信息
     * @param id 附件ID
     * @return 附件详情
     */
    @Override
    public SiteLabourStaffSalaryAnnex getAnnex(Long id) {
        return annexMapper.getModelById(id);
    }

    /**
     * 修改劳务工工资
     *
     * @param master 劳务工工资
     * @return 结果
     */
    @Override
    public int updateMaster(SiteLabourStaffSalaryMaster master) {
        master.setSalaryDateYear(master.getSalaryDate().substring(0, 4));
        master.setSalaryDateMonth(master.getSalaryDate().substring(5));
        return masterMapper.update(master);
    }

    /**
     * 修改劳务工工资明细
     *
     * @param detail 劳务工工资明细
     * @return 结果
     */
    @Override
    public int updateDetail(SiteLabourStaffSalaryDetail detail) {
        return detailMapper.update(detail);
    }

    /**
     * 删除劳务工工资
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteMaster(Integer[] ids) {
        for (int i = 0; i < ids.length; i++) {
            // 删除工资附件
            SiteLabourStaffSalaryMaster master = masterMapper.getModelById(ids[i]);
            // 删除附件和草图文件
            String path = MasterConfig.getLabourStaffSalaryPath() + "/" + master.getAnnexUuid();
            FileUtils.deleteDirectory(new File(path));
            annexMapper.deleteByUuid(master.getAnnexUuid());
            // 删除工资明细
            detailMapper.deleteByMasterId(ids[i]);
            // 删除工资主表
            masterMapper.delete(ids[i]);
        }
        return 1;
    }

    /**
     * 删除劳务工工资明细
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    public int deleteDetail(Integer[] ids) {
        return detailMapper.deleteByIds(ids);
    }

    /**
     * 删除劳务工工资附件
     * @param id 主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteAnnex(Long id) {
        // 删除附件记录，并更新明细状态，返回刷新状态 0为不刷新 1为刷新
        int result = 0;
        SiteLabourStaffSalaryAnnex annex = annexMapper.getModelById(id);
        int count = annexMapper.getFileCount(annex.getUuid());
        if (count == 1) {
            result = 1;
            masterMapper.updateAnnexStatus(annex.getUuid(), Constants.NO);
        }
        annexMapper.delete(id);
        return result;
    }

    /**
     * 劳务工工资明细导入
     *
     * @param list 劳务工工资明细
     * @param updateSupport 是否覆盖
     * @param masterId 主表主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult importData(List<SiteLabourStaffSalaryDetail> list, boolean updateSupport, Integer masterId) {
        AjaxResult ajaxResult = new AjaxResult();
        SiteLabourStaffSalaryMaster master = masterMapper.getModelById(masterId);
        // 劳务工集合
        List<SiteLabourStaff> staffList = staffMapper.selectModelListByBid(master.getInstitutionCode());
        // 本月工资集合
        List<SiteLabourStaffSalaryDetail> dbList = detailMapper.selectModelListByMasterId(masterId);
        // excel导入结果集合
        List<ExcelResult> excelResults = new ArrayList<>();
        // 临时存放，验证excel表格数据是否有重复用
        List<SiteLabourStaffSalaryDetail> tempList = new ArrayList<>();
        // 新增、修改集合
        List<SiteLabourStaffSalaryDetail> insertList = new ArrayList<>();
        List<SiteLabourStaffSalaryDetail> updateList = new ArrayList<>();
        // excel起始行
        int index = 2;
        for (SiteLabourStaffSalaryDetail detail : list) {
            detail.setMasterId(masterId);
            // 每一行的记录
            ExcelResult excelResult = new ExcelResult();
            StringBuilder content = new StringBuilder();
            excelResult.setRow(index);
            // 验证数据格式是否正确
            String validateFormat = validateFormat(detail);
            if (StringUtils.isNotEmpty(validateFormat)) {
                content.append(validateFormat);
                excelResult.setStatus(ResultConstants.RESULT_ERROR);
            }
            // 验证数据是否重复
            if (!ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                String validateRepeat = validateRepeat(detail, tempList);
                if (StringUtils.isNotEmpty(validateRepeat)) {
                    content.append(validateRepeat);
                    excelResult.setStatus(ResultConstants.RESULT_ERROR);
                }
            }
            // 验证劳务工是否存在
            if (!ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                String validateStaffIsExits = validateStaffIsExits(detail, staffList);
                if (StringUtils.isNotEmpty(validateStaffIsExits)) {
                    content.append(validateStaffIsExits);
                    excelResult.setStatus(ResultConstants.RESULT_ERROR);
                }
            }
            // 判断数据是更新还是新增
            if (!ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                SiteLabourStaffSalaryDetail db = validateInsertOrUpdate(detail, dbList);
                if (StringUtils.isNotNull(db)) {
                    updateList.add(db);
                    if (!updateSupport) {
                        content.append("劳务工工资已存在;");
                        excelResult.setStatus(ResultConstants.RESULT_ERROR);
                    } else {
                        content.append("覆盖更新;");
                        excelResult.setStatus(ResultConstants.RESULT_SUCCESS);
                    }
                } else {
                    insertList.add(detail);
                    content.append("正确;");
                    excelResult.setStatus(ResultConstants.RESULT_SUCCESS);
                }
            }
            excelResult.setContent(content.toString());
            detail.setRow(index);
            tempList.add(detail);
            index++;
            excelResults.add(excelResult);
        }
        boolean result = true;
        for (ExcelResult excelResult : excelResults) {
            if (ResultConstants.RESULT_ERROR.equals(excelResult.getStatus())) {
                result = false;
                break;
            }
        }
        if (result) {
            // 批量插入和更新
            if (insertList.size() > 0) {
                detailMapper.insertBatchImport(insertList);
            }
            if (updateList.size() > 0) {
                detailMapper.updateBatchImport(updateList);
            }
            ajaxResult.put(ResultConstants.RESULT_TAG_MSG, ResultConstants.RESULT_SUCCESS_MESSAGE);
            ajaxResult.put(ResultConstants.RESULT_TAG_STATUS, ResultConstants.RESULT_SUCCESS);
        } else {
            ajaxResult.put(ResultConstants.RESULT_TAG_MSG, ResultConstants.RESULT_ERROR_MESSAGE);
            ajaxResult.put(ResultConstants.RESULT_TAG_STATUS, ResultConstants.RESULT_ERROR);
        }
        ajaxResult.put(ResultConstants.RESULT_TAG_ROWS, excelResults);
        return ajaxResult;
    }

    /**
     * 验证数据格式是否正确
     *
     * @param detail 数据
     * @return 结果
     */
    private String validateFormat(SiteLabourStaffSalaryDetail detail) {
        StringBuilder sb = new StringBuilder();
        if (StringUtils.isEmpty(detail.getIdNo())) {
            sb.append("身份证号为空;");
        } else if (!CardUtils.is18CardNo(detail.getIdNo())){
            sb.append("身份证号码验证未通过;");
        }
        if (StringUtils.isEmpty(detail.getName())) {
            sb.append("姓名为空;");
        }
        if (StringUtils.isNull(detail.getAttendanceDay())) {
            sb.append("出勤天数为空;");
        }
        if (StringUtils.isNull(detail.getTotalPayAmount())) {
            sb.append("应发工资为空;");
        }
        if (StringUtils.isNull(detail.getFinalPayingAmount())) {
            sb.append("实发工资为空;");
        }
        return sb.toString();
    }

    /**
     * 验证excel是否有重复的身份证号码和姓名
     *
     * @param detail 劳务工工资
     * @param tempList 临时劳务工工资
     * @return 结果
     */
    private String validateRepeat(SiteLabourStaffSalaryDetail detail, List<SiteLabourStaffSalaryDetail> tempList) {
        for (SiteLabourStaffSalaryDetail temp : tempList) {
            if (detail.getIdNo().equals(temp.getIdNo())) {
                return "与第" + temp.getRow() + "行，身份证重复;";
            }
            if (detail.getName().equals(temp.getName())) {
                return "与第" + temp.getRow() + "行，姓名重复;";
            }
        }
        return "";
    }

    /**
     * 验证excel导入的劳务工是否存在
     *
     * @param detail 劳务工工资
     * @param staffList 劳务工集合
     * @return 结果
     */
    private String validateStaffIsExits(SiteLabourStaffSalaryDetail detail, List<SiteLabourStaff> staffList) {
        if (StringUtils.isNull(staffList) || staffList.size() == 0) {
            return "劳务工未登记;";
        }
        int flag = 0;
        for (SiteLabourStaff staff : staffList) {
            if (staff.getIdNo().equals(detail.getIdNo()) && !staff.getName().equals(detail.getName())) {
                return "劳务工身份证号码和姓名不匹配;";
            }
            if (staff.getIdNo().equals(detail.getIdNo()) && staff.getName().equals(detail.getName())) {
                detail.setStaffId(staff.getId());
                detail.setBattalionId(staff.getBattalionId());
                detail.setTeamId(staff.getTeamId());
                detail.setPostId(staff.getPostId());
                detail.setCreateBy(SecurityUtils.getUsername());
                detail.setCreateTime(DateUtils.getNowDate());
                flag = 1;
            }
        }
        if (flag == 0) {
            return "劳务工未登记;";
        } else {
            return "";
        }
    }

    /**
     * 验证数据是新增还是更新
     *
     * @param detail excel导入数据
     * @param dbList 数据库存在数据
     * @return 数据库已存在数据
     */
    private SiteLabourStaffSalaryDetail validateInsertOrUpdate(SiteLabourStaffSalaryDetail detail, List<SiteLabourStaffSalaryDetail> dbList) {
        for (SiteLabourStaffSalaryDetail db : dbList) {
            if (detail.getStaffId().equals(db.getStaffId())) {
                db.setAttendanceDay(detail.getAttendanceDay());
                db.setTotalPayAmount(detail.getTotalPayAmount());
                db.setFinalPayingAmount(detail.getFinalPayingAmount());
                db.setUpdateBy(SecurityUtils.getUsername());
                db.setUpdateTime(DateUtils.getNowDate());
                return db;
            }
        }
        return null;
    }

}
